<!--
 * @Author: aster lipian1004@163.com
 * @Date: 2025-02-20 17:12:13
 * @FilePath: \aster-flowable-uniapp\src\components\form\render\user-picker.vue
 * @Description: 人员
 * Copyright (c) 2025 by Aster, All Rights Reserved.
-->
<template>
  <van-field
    v-if="!_hidden"
    :name="formItemProp"
    :readonly="_readonly"
    :required="_required"
    :rules="_rules"
    :input-align="FieldInputAlignEnum.RIGHT"
    :error-message-align="FieldInputAlignEnum.RIGHT"
    :label-width="showLabel ? '' : '5rpx'"
    :placeholder="_placeholder"
    is-link
    @click="handleOpen"
  >
    <template #label>
      <text v-if="showLabel">{{ formItem.title }}</text>
    </template>
    <template #extra>
      <view class="field-right" v-if="isNotEmpty(_name_value)">
        <van-tag
          type="primary"
          class="!p-8rpx m-5rpx"
          v-for="(item, index) in _name_value"
          :key="index"
        >
          {{ item }}
        </van-tag>
      </view>
    </template>
  </van-field>

  <van-popup v-model:show="showPicker" round position="bottom" class="user-data-container">
    <!-- 导航 -->
    <view class="card">
      <view class="nav-container">
        <span
          class="nav-name"
          v-for="(navItem, index) in navData"
          :key="index"
          @click="pop(navItem, index)"
        >
          <span class="interval" v-if="index !== 0">|</span>
          <i v-if="navItem.icon" :class="navItem.icon" style="padding: 0 8rpx" />
          <span v-else style="padding: 0 8rpx">{{ navItem.name }}</span>
        </span>
      </view>
    </view>
    <!-- 部门 -->
    <view class="card">
      <van-cell
        :title="deptItem.name"
        size="large"
        v-for="(deptItem, index) in deptData"
        :key="index"
      >
        <template #right-icon>
          <view class="cell-icon" @click="nextGrade(deptItem)">
            <van-icon name="list-switch" class="suffix-icon" />
            <span class="suffix-text">下级</span>
          </view>
        </template>
      </van-cell>
    </view>

    <!-- 人员 -->
    <view class="card">
      <van-checkbox-group v-model="_id_value">
        <van-cell
          :title="userItem.name"
          size="large"
          clickable
          v-for="(userItem, index) in userData"
          :key="index"
          @click="clickItem(userItem, index)"
        >
          <template #right-icon>
            <van-checkbox
              :name="userItem.id"
              :ref="(el) => (checkboxRefs[index] = el)"
              @click.stop="clickItem(userItem, index)"
            />
          </template>
        </van-cell>
      </van-checkbox-group>
      <van-empty description="暂无人员" v-if="userData.length < 1" />
    </view>

    <aster-tabbar
      ref="userTabbarRef"
      :customStyle="{
        borderTopLeftRadius: '10px',
        borderTopRightRadius: '10px',
      }"
    >
      <van-button type="primary" block @click="onConfirm">确定选择</van-button>
    </aster-tabbar>
  </van-popup>
</template>
<script setup lang="ts">
  import { evaluateFormula } from '@/utils/workflow';
  import { computed, PropType, ref, watch, watchEffect } from 'vue';
  import { isNotEmpty, isEmpty, isArray } from '@/utils/is';
  import { FormPermissionEnum } from '@/enums/workFlowEnum';
  import { FieldInputAlignEnum } from '@/enums/formEnum';
  import { onLoad } from '@dcloudio/uni-app';
  import {
    userDeptInfoApi,
    userAllApi,
    selectUsersByDeptIdsApi,
    selectUsersByRoleIdsApi,
  } from '@/api/sys/user';
  import { Toast } from '@/utils/uniapi/prompt';
  import AsterTabbar from '@/components/common/aster-tabbar.vue';
  import { instanceInfoByCustomParamsApi } from '@/api/workflow/process';
  import { memberByRoleIdsApi } from '@/api/workflow/auth';

  const emit = defineEmits(['update:value']);
  const props = defineProps({
    value: {
      type: Array as PropType<string[]>,
      default: () => [],
    },
    mode: {
      type: String as PropType<'design' | 'form' | 'search' | 'table' | 'print'>,
      default: 'design',
    },
    formData: {
      type: Object as PropType<WorkForm.FormDataModel>,
      default: {},
    },
    formItem: {
      type: Object as PropType<WorkComponent.ComponentConfig>,
      default: {},
    },
    tableId: {
      type: String,
      default: '',
    },
    tableIndex: {
      type: Number,
      default: 0,
    },
    showLabel: {
      type: Boolean,
      default: true,
    },
  });

  const checkboxRefs = ref<any[]>([]);
  // 显示弹出层
  const showPicker = ref(false);
  // 所有用户信息
  const userList = ref<User.UserInfo[]>([]);
  // 导航数据
  const navData = ref<User.UserDeptModel[]>([]);
  // 用户数据
  const userData = ref<User.UserDeptModel[]>([]);
  // 部门数据
  const deptData = ref<User.UserDeptModel[]>([]);
  // 是否多选, 默认单选
  const multiple = ref<boolean>(false);
  // value
  const _value = ref<User.UserDeptModel[]>([]);
  // checkbox value
  const _id_value = ref<string[]>([]);
  // 用于展示的 value
  const _name_value = ref<string[]>([]);
  // 限制使用的用户ID
  const limitUserIds = ref<string[]>([]);

  // 打开弹出层
  const handleOpen = () => {
    if (!_readonly.value) {
      showPicker.value = true;
    }
  };

  /**
   * @description: 点击导航
   * @param deptItem 部门对象
   * @param index 导航索引
   */
  const pop = (dept: User.UserDeptModel, index: number) => {
    navData.value = navData.value.slice(0, index + 1);
    getUserDeptData(dept.id);
  };

  /**
   * @description: 下一级
   * @param deptItem 部门对象
   */
  const nextGrade = (dept: User.UserDeptModel) => {
    navData.value.push(dept);
    getUserDeptData(dept.id);
  };

  /**
   * @description: 根据部门id批量查询用户信息
   * @param {*} ids 部门id集合
   * @return {*}
   */
  const getUsersByDeptIdsApi = async (ids: string[]) => {
    await selectUsersByDeptIdsApi(ids).then(({ data }) => {
      // limitUserIds.value 不存在id，则添加
      data.forEach((item: User.UserInfo) => {
        if (!limitUserIds.value.includes(item.id)) {
          limitUserIds.value.push(item.id);
        }
      });
    });
  };

  /**
   * @description: 根据系统角色id批量查询用户信息
   * @param {*} ids 角色id集合
   * @return {*}
   */
  const getUsersByRoleIdsApi = async (ids: string[]) => {
    await selectUsersByRoleIdsApi(ids).then(({ data }) => {
      // limitUserIds.value 不存在id，则添加
      data.forEach((item: Role.RoleUserInfo) => {
        if (!limitUserIds.value.includes(item.userId)) {
          limitUserIds.value.push(item.userId);
        }
      });
    });
  };

  /**
   * @description: 获取流程角色ID查询用户信息
   * @param {*} ids 角色id集合
   * @return {*}
   */
  const getUsersByFlowRoleApi = async (ids: string[]) => {
    await memberByRoleIdsApi(ids).then(({ data }) => {
      // limitUserIds.value 不存在id，则添加
      data.forEach((item: WorkAuth.MemberInfo) => {
        if (item.memberId && !limitUserIds.value.includes(item.memberId)) {
          limitUserIds.value.push(item.memberId);
        }
      });
    });
  };

  /**
   * @description: 获取用户部门数据
   */
  const getUserDeptData = async (deptId: string) => {
    userData.value = [];
    deptData.value = [];
    limitUserIds.value = [];
    // 限制类型, 用户ID | 部门ID | 系统角色ID | 流程角色ID
    const type = _canselected.value?.type;
    const ids = _canselected.value?.ids;
    // 判断ids是否有值，有则需要做权限筛选，获取需要过滤的用户id
    if (ids && isNotEmpty(ids)) {
      switch (type) {
        case 'user':
          limitUserIds.value = ids;
          break;
        case 'dept':
          // 通过部门id批量查询部门下的所有用户
          getUsersByDeptIdsApi(ids);
          break;
        case 'sysRole':
          // 通过角色id批量查询角色下的所有用户
          getUsersByRoleIdsApi(ids);
          break;
        case 'flowRole':
          getUsersByFlowRoleApi(ids);
          break;
        default:
          break;
      }
    }
    await userDeptInfoApi(deptId).then(({ data }) => {
      if (data && data.length > 0) {
        data.forEach((item) => {
          if (item.type == 'dept') {
            deptData.value.push(item);
          } else if (item.type == 'user') {
            userData.value.push(item);
            // 过滤userData，排除在limitUserIds数组中不存在的数据
            if (limitUserIds.value.length > 0) {
              userData.value = userData.value.filter((item: User.UserDeptModel) => {
                return limitUserIds.value.some((id: string) => {
                  return item.id === id;
                });
              });
            }
          }
        });
      }
    });
  };

  /**
   * @description: 点击人员
   * @param userItem 用户对象
   */
  const clickItem = (user: User.UserDeptModel, index: number) => {
    checkboxRefs.value[index].toggle();
    // 如果单选
    if (!multiple.value) {
      if (_id_value.value.length > 0) {
        _id_value.value = [user.id];
        _value.value = [user];
      } else {
        _value.value = [];
      }
    } else {
      // 如果存在
      if (_id_value.value.indexOf(user.id) !== -1) {
        _value.value.push(user);
      } else {
        for (let i = 0; i < _value.value.length; i++) {
          if (_value.value[i].id === user.id) {
            _value.value.splice(i, 1);
          }
        }
      }
    }
  };

  /**
   * @description: 确认选择
   */
  const onConfirm = () => {
    if (_required.value && isEmpty(_value.value)) {
      Toast('请至少选择一个' + props.formItem.title);
      return false;
    }
    _name_value.value = [];
    for (let i = 0; i < _value.value.length; i++) {
      _name_value.value.push(_value.value[i].name);
    }
    const userIds = isNotEmpty(_value.value) ? _value.value.map((item) => item.id) : [];
    emit('update:value', userIds);
    showPicker.value = false;
  };

  // 键
  const formItemProp = computed(() => {
    if (isNotEmpty(props.tableId)) {
      return props.tableId + '.' + props.tableIndex + '.' + props.formItem.id;
    } else {
      return props.formItem.id;
    }
  });

  /**
   * @description: 提示词
   */
  const _placeholder = computed(() => {
    if (_readonly.value) {
      return '';
    }
    console.log(_value.value);
    console.log(props.formData);
    return isNotEmpty(_value.value) ? '' : props.formItem.props.placeholder;
  });

  /**
   * @description: 是否必填, true-必填
   */
  const _required = computed(() => {
    return props.formItem.props.required;
  });

  /**
   * @description: 是否只读, true-只读
   */
  const _readonly = computed(() => {
    let r = props.formItem.props.readonly;
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.READONLY;
    }
    return r;
  });

  /**
   * @description: 校验规则
   */
  const _rules = computed(() => {
    const isRequired = _required.value;
    if (props.mode != 'form') {
      return [];
    }
    return isRequired ? [{ required: true, message: `请输入${props.formItem.title}` }] : [];
  });

  /**
   * @description: 是否隐藏, true-隐藏
   */
  const _hidden = computed(() => {
    let r = false;
    // 解析隐藏条件公式
    if (props.formItem.props.hidden) {
      let expression = props.formItem.props.hidden;
      // 如果是子表中的控件，则需要用到下标
      if (isNotEmpty(props.tableId)) {
        expression = expression.replaceAll('?', props.tableIndex);
      }
      r = evaluateFormula(expression, props.formData);
    }
    // 判断流程节点下该控件是否隐藏
    if (props.formItem.operation && props.formItem.operation.length > 0) {
      r = r || props.formItem.operation[0] == FormPermissionEnum.HIDDEN;
    }
    return r;
  });

  /**
   * @description: 限制选中人员
   */
  const _canselected = computed(() => {
    return props.formItem.props?.canselected;
  });

  /**
   * @description: 监听表单数据变化
   */
  const _formData = computed(() => {
    return JSON.parse(JSON.stringify(props.formData));
  });

  /**
   * @description: 监听表单数据变化
   */
  watch(
    () => _formData.value,
    async (nval, oval) => {
      if (nval && props.formItem && props.formItem.props.default) {
        // 默认值-数据联动
        const defaultConfig = props.formItem.props.default;
        if (
          defaultConfig.type === 'linkage' &&
          isNotEmpty(defaultConfig.linkage.formCode) &&
          isNotEmpty(defaultConfig.linkage.conditions) &&
          isNotEmpty(defaultConfig.linkage.dataFill)
        ) {
          const conditionStr = JSON.stringify(defaultConfig.linkage.conditions);
          Object.keys(nval).forEach(async (key) => {
            // 判断联动条件中的当前表单的字段的值是否有变动，如有则重新赋值
            if (conditionStr.indexOf(key) != -1 && oval != undefined && nval[key] != oval[key]) {
              const targetCode = defaultConfig.linkage.formCode[1];
              let targetParams = {};
              defaultConfig.linkage.conditions.forEach((item) => {
                if (isNotEmpty(item.currentFieldId) && isNotEmpty(item.associatedFieldId)) {
                  targetParams[item.associatedFieldId] = nval[item.currentFieldId];
                }
              });
              // 根据条件查询目标表单的流程实例
              await instanceInfoByCustomParamsApi(targetCode, targetParams).then(({ data }) => {
                if (data) {
                  const dataFill = defaultConfig.linkage.dataFill;
                  // 如果目标表单中存在该填充字段，则赋值
                  if (data.hasOwnProperty(dataFill) && isNotEmpty(data[dataFill])) {
                    const associatedValue = data[dataFill];
                    if (isArray(associatedValue)) {
                      _value.value = associatedValue;
                    } else {
                      _value.value =
                        associatedValue.indexOf('[') != -1 ? JSON.parse(associatedValue) : [];
                    }
                  } else {
                    _value.value = props.formItem.value;
                  }
                } else {
                  // 流程实例不存在则重置为空
                  _value.value = props.formItem.value;
                }
              });
            }
          });
        }
      }
    },
    { immediate: true, deep: true },
  );

  /**
   * @description: 获取所有用户信息
   */
  const getAllUserInfo = async () => {
    await userAllApi().then(({ data }) => {
      userList.value = data;
      init();
    });
  };

  // 初始化赋值
  const init = () => {
    if (isNotEmpty(props.value) && isNotEmpty(userList.value)) {
      _id_value.value = JSON.parse(JSON.stringify(props.value));
      _value.value = userList.value
        .filter((f) => {
          return f.id && props.value.indexOf(f.id) !== -1;
        })
        .map((m) => {
          const name = m.realName ? m.realName : m.nickName;
          return { id: m.id ? m.id : '', name: name ? name : '', type: 'user' };
        });
      _name_value.value = _value.value.map((m) => {
        return m.name;
      });
    }
  };

  onLoad(async () => {
    multiple.value = props.formItem.props.multiple;
    await getAllUserInfo();
    navData.value.push({ id: '0', name: '全部', type: 'dept', icon: 'iconfont icon-SmartHome' });
    await getUserDeptData('0');
  });

  defineExpose({
    _hidden,
  });
</script>
<style scoped lang="scss">
  .user-data-container {
    background-color: #f8f8f8;
    height: 60%;
  }
  .card {
    width: 100%;
    margin-top: 20rpx;
  }

  .cell-icon {
    height: 100%;
    line-height: 1;
  }

  .suffix-icon {
    color: #1989fa;
    scale: (1.1);
  }

  .suffix-text {
    color: #1989fa;
  }

  .nav-container {
    height: 35px;
    padding-left: 10px;
    font-size: 16px;
    display: flex;
    align-items: center;
  }

  .interval {
    padding: 0px 3px;
    color: #959292;
  }

  .nav-name {
    color: #1989fa;
  }
  .field-right {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
  }
</style>
